package com.rmv.ums.configuration.model;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Element;

import com.rmv.ums.configuration.Configuration;

public class ConfigurableNodeFactory {

	// constants
	private static final String CONFIGURABLE_NODE_CLASS_PATTERN = "{0}.type.{1}.class";
	private static final String DEFAULT_KEY = "default";

	private static Map clazzes = new HashMap();

	public static ConfigurableNode get(String typeNode, Element element) throws ConfigurableNodeException {
		// get class
		String clazz = element.attributeValue("class");
		if (StringUtils.isBlank(clazz)) {
			String type = element.attributeValue("type");
			if (StringUtils.isBlank(type)) {
				type = DEFAULT_KEY;
			}
			String key = MessageFormat.format(CONFIGURABLE_NODE_CLASS_PATTERN, new String[] { typeNode, type });
			clazz = Configuration.getInstance().getConfigurationValue(key);
		}

		// Instantiate response
		ConfigurableNode node = null;
		try {
			node = (ConfigurableNode) getObject(clazz);
		} catch (ClassNotFoundException e) {
			throw new ConfigurableNodeException("element class not found", e);
		} catch (InstantiationException e) {
			throw new ConfigurableNodeException("problem instantiating element", e);
		} catch (IllegalAccessException e) {
			throw new ConfigurableNodeException("illegal access to element", e);
		}

		// configure response
		boolean configure = node.configure(element);
		if (!configure) {
			throw new ConfigurableNodeException("error configuring node:" + element.asXML());
		}

		return node;
	}

	private static Object getObject(String clazz) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

		Class cls = (Class) clazzes.get(clazz);
		if (cls == null) {
			cls = Class.forName(clazz);
			clazzes.put(clazz, cls);
		}
		return cls.newInstance();
	}
}
